package com.maiji.cloud.controller;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.maiji.cloud.entities.login.AppUser;
import com.maiji.cloud.entities.login.UserInfo;
import com.maiji.cloud.mapper.AppUserMapper;
import com.maiji.cloud.microservice.CapitalMainMService;
import com.maiji.cloud.request.BaseDataReqDto;
import com.maiji.cloud.request.login.BaiduXCXReqData;
import com.maiji.cloud.request.login.XCXBindTelReqData;
import com.maiji.cloud.request.login.XCXLoginReqData;
import com.maiji.cloud.response.BaseDataResDto;
import com.maiji.cloud.response.Status;
import com.maiji.cloud.response.login.XCXLoginResData;
import com.maiji.cloud.service.AppUserService;
import com.maiji.cloud.service.UserService;
import com.maiji.cloud.utils.NuomiSignature;
import com.maiji.cloud.utils.RedisUtil;
import com.maiji.cloud.utils.UUID_MD5;
import com.nuomi.common.NuomiApiException;
import org.apache.commons.lang3.StringUtils;
import com.maiji.cloud.utils.AES;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/bd/")
public class BDController {

    private static final Logger logger = LoggerFactory.getLogger(BDController.class);
    @Value("${bd.appkey}")
    private String appkey;
    @Value("${bd.secret}")
    private String secret;
    @Value("${bd.url}")
    private String url;
    @Autowired
    private AppUserService appUserService;
    @Autowired
    private UserService userService;
    @Autowired
    private CapitalMainMService capitalMainMService;
    @Autowired
    private RedisTemplate<String, Object> maiji1RedisTemplate;
    @Autowired
    private RedisTemplate<String, Object> maiji2RedisTemplate;
    @Autowired
	private AppUserMapper appUserMapper;

    @PostMapping("/login")
    public BaseDataResDto<XCXLoginResData> logon (@RequestBody BaseDataReqDto<XCXLoginReqData> baseDataReqDto) {
        XCXLoginReqData data = baseDataReqDto.getData();
        String jsCode = data.getJsCode();
        if (StringUtil.isBlank(jsCode)) return new BaseDataResDto<>(Status.PARAMETERERROR);
        Map<String, String> param = new HashMap<>();
        param.put("client_id", appkey);
        param.put("sk", secret);
        param.put("code", jsCode);
        logger.info("BDController.bd.login ===>> param: " + JSON.toJSONString(param));
//        JSONObject jsonObject = JSON.parseObject(new RestTemplate().getForObject(url, String.class, param));
        JSONObject jsonObject = JSON.parseObject(new RestTemplate().postForObject(url, param, String.class));
        logger.info("BDController.bd.login ===>> jsonObject: " + jsonObject.toJSONString());
        if (jsonObject.getString("error") != null) return new BaseDataResDto<>(Status.ERROR);
        XCXLoginResData bdLoginResData = new XCXLoginResData()
                .setSession_key((String) jsonObject.get("session_key"))
                .setOpenid((String) jsonObject.get("openid"));
        return new BaseDataResDto<XCXLoginResData>(Status.SUCCESS).setData(bdLoginResData);
    }

    @PostMapping("/bindTel")
    public BaseDataResDto<String> bindTel (@RequestBody BaseDataReqDto<XCXBindTelReqData> baseDataReqDto) {
        XCXBindTelReqData data = baseDataReqDto.getData();
        String openIdWX = data.getOpenId();
        if (StringUtil.isBlank(openIdWX)) return new BaseDataResDto<>(Status
                .USER_WORNING_INFO.setMessage("绑定手机号失败，请重新打开小程序后再试"));
        String phoneNumber;
        if (StringUtil.isNotBlank(data.getTel())) {
            phoneNumber = data.getTel();
            if (! appUserService.checkCode(phoneNumber, data.getCode())) return new BaseDataResDto(Status.IDENTIFYCODEINVALID);
        } else {
//             1.解析加密数据
            String encryptedData = data.getEncryptedData();
            String sessionKey = data.getSessionKey();
            String iv = data.getIv();
            cn.hutool.json.JSONObject userencryptedData = AES.bdDecrypt(encryptedData, sessionKey, iv);
            phoneNumber = (String) userencryptedData.get("mobile");
        }
        if (StringUtil.isBlank(phoneNumber) || ! phoneNumber.matches("^[1][0-9]{10}$"))
            return new BaseDataResDto(Status.PARAMETERERROR);
        // 验证手机号是否已注册
        EntityWrapper<AppUser> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("tel", phoneNumber);
        entityWrapper.or();
        entityWrapper.eq("open_id_bd", openIdWX);
        AppUser appUser = appUserService.selectOne(entityWrapper);
        if (appUser == null) {  // 未注册
            String pwd = UUID_MD5.randomPwd();
            String tokenBd = UUID_MD5.md5Str(phoneNumber + pwd.toUpperCase() + System.currentTimeMillis());
            appUser = new AppUser().setUuId(UUID_MD5.getUUID()).setOpenIdBd(data.getOpenId()).setPwd(UUID_MD5.md5Str(pwd))
                    .setTokenBd(tokenBd).setTokenStatusBd(1).setRegDate(new Date()).setTel(phoneNumber).setIsBan(0);
            if(StringUtils.isNotBlank(data.getDistributionNum())) {
                String pidUserId = checkDistributionNum(data.getDistributionNum());
                if(StringUtils.isBlank(pidUserId)) return new BaseDataResDto(Status.PARAMETERERROR);
                appUserService.logonPidCount(appUser.setPid(pidUserId));
            }
            if (! appUserService.insert(appUser)) return new BaseDataResDto<>(Status.APPUSERINSERTFAILED);
            if (! capitalMainMService.createCapitalMain(appUser.getUuId()))
                return new BaseDataResDto<>(Status.ERROR.setMessage("创建用户资金账户失败！"));
        } else {  // 已注册
            if (appUser.getIsBan() == 1) return new BaseDataResDto(Status.USER_WORNING_INFO.setMessage("该账户已被禁止登录"));
            String tokenBdNew = UUID_MD5.md5Str(phoneNumber + appUser.getPwd().toUpperCase() + System.currentTimeMillis());
            appUser.setOpenIdBd(data.getOpenId()).setTel(phoneNumber).setTokenBd(tokenBdNew).setTokenStatusBd(1);
            if (! appUserService.updateById(appUser)) return new BaseDataResDto<>(Status.APPUSERINSERTFAILED);
        }
        //保存用户头像
        UserInfo userInfo = userService.selectOne(new EntityWrapper<UserInfo>().eq("user_id", appUser.getUuId()));
        if (userInfo == null) {
            userInfo = new UserInfo().setUuId(UUID_MD5.getUUID()).setUserId(appUser.getUuId()).setSex(data.getSex())
                    .setNickName(data.getNickName()).setHeadUrl(data.getHeadUrl()).setRegDate(new Date());
            if (! userService.insert(userInfo)) return new BaseDataResDto<>(Status.ERROR.setMessage("保存用户基本信息失败！"));
        } else {
            if (StringUtil.isBlank(userInfo.getNickName()) || userInfo.getNickName().startsWith("Maiji-")) userInfo.setNickName(data.getNickName());
            if (StringUtil.isBlank(userInfo.getHeadUrl())) userInfo.setNickName(data.getNickName());
            if (userInfo.getSex() == null) userInfo.setSex(data.getSex());
            if (! userService.updateById(userInfo)) return new BaseDataResDto<>(Status.ERROR.setMessage("保存用户基本信息失败！"));
        }
        RedisUtil.setObject(maiji1RedisTemplate, "maijiToken:" + appUser.getTokenBd(), appUser);
        if (maiji2RedisTemplate != null) RedisUtil.setObject(maiji2RedisTemplate, "maijiToken:" + appUser.getTokenBd(), appUser);
        return new BaseDataResDto<String>(Status.SUCCESS).setData(appUser.getTokenBd());
    }

    @PostMapping("/openidLogin")
    public BaseDataResDto<String> openidLogin (@RequestBody BaseDataReqDto<String> baseDataReqDto) {
        String openIdBD = baseDataReqDto.getData();
        if (StringUtil.isBlank(openIdBD)) return new BaseDataResDto<>(Status.USER_WORNING_INFO.setMessage("登录失败，请重新打开小程序后再试"));
        AppUser appUser = appUserService.selectOne(new EntityWrapper<AppUser>().eq("open_id_bd", openIdBD));
        if (appUser == null) return new BaseDataResDto(Status.UNREGISTERED);
        if (appUser.getIsBan() == 1) return new BaseDataResDto(Status.USER_WORNING_INFO.setMessage("该账户已被禁止登录"));
        String tokenBdNew = UUID_MD5.md5Str(appUser.getTel() + appUser.getPwd().toUpperCase() + System.currentTimeMillis());
        appUser.setTokenBd(tokenBdNew).setTokenStatusBd(1);
        if (! appUserService.updateById(appUser)) return new BaseDataResDto<>(Status.APPUSERINSERTFAILED);
        RedisUtil.setObject(maiji1RedisTemplate, "maijiToken:" + appUser.getTokenBd(), appUser);
        if (maiji2RedisTemplate != null) RedisUtil.setObject(maiji2RedisTemplate, "maijiToken:" + appUser.getTokenBd(), appUser);
        return new BaseDataResDto<String>(Status.SUCCESS).setData(appUser.getTokenBd());
    }

    @PostMapping("/rsaSign")
    public BaseDataResDto<String> rsaSign (@RequestBody BaseDataReqDto<BaiduXCXReqData> baseDataReqDto) {
        Double totalAmount = baseDataReqDto.getData().getTotalAmount();
        String tpOrderId = baseDataReqDto.getData().getTpOrderId();
        String totalAmountStr = NumberUtil.toStr(totalAmount * 100);
        try {
            String sign = NuomiSignature.genSignWithRsa(totalAmountStr, tpOrderId);
            return new BaseDataResDto<String>(Status.SUCCESS).setData(sign);
        } catch (NuomiApiException e) {
            e.printStackTrace();
            return new BaseDataResDto<>(Status.ERROR);
        }
    }

    /**
	 * 根据分销码查看用户id并校验分销码是否正确
	 * @param distributionNum
	 * @return
	 */
	public String checkDistributionNum(String distributionNum) {
		if (StringUtil.isBlank(distributionNum)) return null;
		AppUser appUser = appUserMapper.selectOne(new AppUser().setDistributionNum(distributionNum));
		if(appUser != null) return appUser.getUuId();
		return null;
	}

}
